export class BowlingGame {
  name = "Bowling Game"
  rounds: Round[] = []
  currentRound = 0

  constructor() {
    this.rounds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(n => new Round(this, n))
  }

  getRound(n:number) {
    return this.rounds[n-1]
  }

  parseStr(roundStr: string) {
    let arrResult: number[] = []
    roundStr.split('').forEach((v, i) => {
      if (v === 'X') {
        arrResult.push(10)
      } else if (v === '-') {
        arrResult.push(0)
      } else if (v === '/') {
        const t = 10 - arrResult[i - 1]
        arrResult.push(t)
      } else {
        arrResult.push(Number.parseInt(v))
      }
    })
    return arrResult
  }

  setRolls(rolls: string) {
    rolls.split(' ').forEach((roll, i) => {
      const rs = this.parseStr(roll)
      this.rounds[i].firstRoll(rs[0])
      if (rs.length > 1) {
        this.rounds[i].secondRoll(rs[1])
      }
      if (rs.length > 2) {
        this.rounds[i].thirdRoll(rs[2])
      }
    })
  }

  getTotal() {
    return this.rounds.reduce((pre, current) => pre + current.score, 0)
  }
}

class Round {
  static MAX_BALL = 10;

  no = 0;
  firstNumber = 0;
  score = 0;
  secondNumber = 0;
  isSpare = false;
  isStrike = false;
  isOver = false; // TODO Check the wrong number or score. 
  thirdNumber = 0;

  constructor(private bowlingGame: BowlingGame, n: number) {
    this.bowlingGame = bowlingGame;
    this.no = n;
  }

  preRound() {
    return this.bowlingGame.getRound(this.no - 1);
  }

  prePreRound() {
    return this.bowlingGame.getRound(this.no - 2);
  }

  firstRoll(m: number) {
    this.bowlingGame.currentRound = this.no;
    this.firstNumber = m;
    if (this.firstNumber === Round.MAX_BALL) {
      this.isStrike = true;
      this.isOver = true;
    }
    this.score += this.firstNumber;
    let preRound = this.preRound();
    if (preRound && (preRound.isStrike || preRound.isSpare)) {
      preRound.score += this.firstNumber;
    }
    let prePreRound = this.prePreRound();
    if (prePreRound && prePreRound.isStrike && preRound.isStrike) {
      prePreRound.score += this.firstNumber;
    }
  }
  secondRoll(n: number) {
    this.secondNumber = n;
    this.score += this.secondNumber;
    if (this.firstNumber + this.secondNumber === Round.MAX_BALL) {
      this.isSpare = true;
    }
    let preRound = this.preRound();
    if (preRound && preRound.isStrike) {
      preRound.score += this.secondNumber;
    }
    this.isOver = !this.isSpare && !this.isStrike;
  }

  thirdRoll(n: number) {
    if (this.no === 10 && (this.isStrike || this.isSpare)) {
      this.thirdNumber = n;
      this.score += this.thirdNumber
    } else {
      throw new Error("Can not roll this time");
    }
    this.isOver = true
  }
}